#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int a[3][2] = {{1, 2},
                   {3, 4},
                   {5, 6}};
    // 第一种：二维数组指针，指向整个二维数组
    int(*ptr1)[3][2] = &a;
    printf("%p\n", ptr1);

    printf("-----\n");

    // 第二种：一维数组指针，指向二维数组第一行元素
    int(*ptr2)[2] = &a[0]; // 等同于int(*ptr2)[2] = a; // 数组名是其第一个元素的指针
    printf("%p\n", ptr2);
    ptr2 = a;
    printf("%p\n", ptr2);

    printf("-----\n");

    // 第三种：int *型指针，指向二维数组第一行第一列的第一个元素
    int *ptr3 = &a[0][0]; // 等同于int *ptr3 = a[0]; 也等同于 int *ptr3 = *a; // 数组名是其第一个元素的指针
    printf("%p\n", ptr3);
    ptr3 = a[0];
    printf("%p\n", ptr3);
    ptr3 = *a;
    printf("%p\n", ptr3);

    printf("-----\n");
    // 第四种：int *型指针，指向二维数组第一行元素
    int **ptr4 = calloc(3, sizeof(int *));
    for (int i = 0; i < 3; i++)
    {
        *(ptr4 + i) = *(a + i);
        printf("%p\n", *(ptr4 + i));
    }
    printf("%d\n", *(*(ptr4 + 2) + 0)); // 5 等同于a[2][0]
    printf("%d\n", *(*(ptr4 + 2) + 1)); // 6 等同于a[2][1]

    printf("-----\n");

    int b[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};

    for (int i = 0; i < 3; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            printf("%p ", &b[i][j]);
        }
        printf("\n");
    }

    printf("\n");

    int(*p0)[3] = &b[0];
    int(*p1)[3] = &b[1];
    int(*p2)[3] = &b[2];

    printf("%d %d %d\n", *(*p0 + 0), *(*p0 + 1), *(*p0 + 2));
    printf("%d %d %d\n", *(*p1 + 0), *(*p1 + 1), *(*p1 + 2));
    printf("%d %d %d\n", *(*p2 + 0), *(*p2 + 1), *(*p2 + 2));

    printf("-----\n");

    int c[3] = {11, 22, 33};
    printf("%p %p %p\n", &c[0], &c[1], &c[2]);
    int(*p4)[3] = &c;
    printf("%p %p %p \n", c, p4, *p4);

    return 0;
}